# The BUILD file for p4testgen, inspired by the tool's cmake build rules.

load("@bazel_skylib//rules:build_test.bzl", "build_test")

package(
    default_applicable_licenses = ["//:license"],
    licenses = ["notice"],
)

# Extend the list with the name of the desired targets (in "modules/testgen/targets/).
TESTGEN_TARGETS = ["bmv2"]

filegroup(
    name = "ir_extension",
    srcs = ["p4tools.def"],
    visibility = ["//visibility:public"],  # So p4c can compile these.
)

proto_library(
    name = "ir_proto",
    srcs = ["modules/testgen/targets/bmv2/proto/ir.proto"],
    deps = [
        "@com_github_p4lang_p4runtime//:p4info_proto",
        "@com_github_p4lang_p4runtime//:p4runtime_proto",
        "@com_google_googleapis//google/rpc:code_proto",
        "@com_google_googleapis//google/rpc:status_proto",
    ],
)

proto_library(
    name = "p4testgen_proto",
    srcs = ["modules/testgen/targets/bmv2/proto/p4testgen.proto"],
    deps = ["@com_github_p4lang_p4runtime//:p4runtime_proto"],
)

proto_library(
    name = "p4testgen_ir_proto",
    srcs = ["modules/testgen/targets/bmv2/proto/p4testgen_ir.proto"],
    deps = [":ir_proto"],
)

cc_proto_library(
    name = "p4testgen_cc_proto",
    visibility = ["//visibility:public"],
    deps = [":p4testgen_proto"],
)

cc_proto_library(
    name = "p4testgen_ir_cc_proto",
    visibility = ["//visibility:public"],
    deps = [":p4testgen_ir_proto"],
)

genrule(
    name = "version",
    srcs = [
        "common/version.h.in",
    ],
    outs = ["common/version.h"],
    cmd = " | ".join([
        "cat $(location common/version.h.in)",
        "sed 's/@P4TOOLS_VERSION_MAJOR@/0/'",
        "sed 's/@P4TOOLS_VERSION_MINOR@/0/'",
        "sed 's/@P4TOOLS_VERSION_PATCH@/0/'",
        "sed 's/@P4TOOLS_VERSION_HASH@/0.0.0/'",
        "tee > $(location common/version.h)",
    ]),
    output_to_bindir = False,
)

cc_library(
    name = "common",
    srcs = glob([
        "common/**/*.h",
        "common/**/*.cpp",
    ]) + [":version"],
    copts = [
        "-fexceptions",
        "-w",
    ],
    features = ["-use_header_modules"],
    deps = [
        "//:ir_frontend_midend_control_plane",
        "//:lib",
        "@boost//:multiprecision",
        "@com_github_p4lang_p4runtime//:p4info_cc_proto",
        "@com_github_z3prover_z3//:api",
        "@com_google_absl//absl/container:btree",
        "@com_google_absl//absl/strings:str_format",
    ],
)

filegroup(
    name = "target_register_headers",
    srcs = ["modules/testgen/targets/%s/register.h" % target for target in TESTGEN_TARGETS],
)

genrule(
    name = "register_testgen_targets",
    srcs = [
        ":target_register_headers",
        "modules/testgen/register.h.in",
    ],
    outs = ["modules/testgen/register.h"],
    cmd = " | ".join([
        "cat $(location modules/testgen/register.h.in)",
        "sed 's/@include_statements_var@/%s/'" % "".join(["#include \"backends\\/p4tools\\/modules\\/testgen\\/targets\\/%s\\/register.h\"\\n" % target for target in TESTGEN_TARGETS]),
        "sed 's/@compiler_targets_var@/%s/'" % "".join(["%sRegisterCompilerTarget();\\n" % target for target in TESTGEN_TARGETS]),
        "sed 's/@testgen_targets_var@/%s/' " % "".join(["%sRegisterTestgenTarget();\\n" % target for target in TESTGEN_TARGETS]),
        "tee > $(location modules/testgen/register.h)",
    ]),
    output_to_bindir = False,
)

filegroup(
    name = "testgen_targets_src",
    srcs =
        glob(
            ["modules/testgen/targets/%s/**/*.h" % target for target in TESTGEN_TARGETS],
            exclude = ["modules/testgen/targets/%s/test/**/*.h" % target for target in TESTGEN_TARGETS],
        ) +
        glob(
            ["modules/testgen/targets/%s/**/*.cpp" % target for target in TESTGEN_TARGETS],
            exclude = ["modules/testgen/targets/%s/test/**/*.cpp" % target for target in TESTGEN_TARGETS],
        ),
)

cc_library(
    name = "testgen_lib",
    srcs = glob([
        "modules/testgen/core/*.cpp",
        "modules/testgen/core/small_step/*.cpp",
        "modules/testgen/core/symbolic_executor/*.cpp",
        "modules/testgen/lib/*.cpp",
    ]) + glob([
        "modules/testgen/core/*.h",
        "modules/testgen/core/small_step/*.h",
        "modules/testgen/core/symbolic_executor/*.h",
        "modules/testgen/lib/*.h",
    ]) + [
        "modules/testgen/options.cpp",
        "modules/testgen/testgen.cpp",
        ":register_testgen_targets",
        ":target_register_headers",
        ":testgen_targets_src",
    ],
    # We onlu make top-level, library, and test backend header files visible to other targets.
    hdrs = ["common/options.h"] + glob([
        "modules/testgen/lib/*.h",
        "modules/testgen/*.h",
    ]) + glob(
        ["modules/testgen/targets/%s/test_backend/*.h" % target for target in TESTGEN_TARGETS],
    ),
    copts = [
        "-fexceptions",
        "-w",
    ],
    features = ["-use_header_modules"],
    # Needs to be accessible by other targets.
    visibility = ["//visibility:public"],
    deps = [
        ":common",
        ":register_testgen_targets",
        "//:ir_frontend_midend_control_plane",
        "//:lib",
        "@boost//:multiprecision",
        "@com_github_pantor_inja//:inja",
        "@com_google_absl//absl/container:btree",
        "@com_google_absl//absl/strings",
        "@nlohmann_json//:json",
    ],
)

cc_binary(
    name = "p4testgen",
    srcs = [
        "modules/testgen/main.cpp",
    ],
    copts = [
        "-fexceptions",
        "-w",
    ],
    features = ["-use_header_modules"],
    visibility = ["//visibility:public"],
    deps = [
        ":testgen_lib",
        "//:lib",
        "@boost//:multiprecision",
    ],
)

build_test(
    name = "p4testgen_build_test",
    targets = [
        ":p4testgen",
    ],
)

cc_library(
    name = "testgen_test_lib",
    srcs = [
        "modules/testgen/targets/bmv2/test/gtest_utils.cpp",
        "modules/testgen/test/gtest_utils.cpp",
        "modules/testgen/test/small-step/util.cpp",
    ],
    hdrs = [
        "modules/testgen/targets/bmv2/test/gtest_utils.h",
        "modules/testgen/test/gtest_utils.h",
        "modules/testgen/test/small-step/util.h",
    ],
    copts = [
        "-fexceptions",
        "-w",
    ],
    deps = [
        ":testgen_lib",
        "//:test_helpers",
        "@com_google_absl//absl/strings",
        "@com_google_googletest//:gtest_main",
    ],
)

cc_test(
    name = "p4testgen_api_test",
    srcs = [
        "modules/testgen/targets/bmv2/test/testgen_api/api_test.cpp",
    ],
    copts = [
        "-fexceptions",
        "-w",
    ],
    deps = [
        ":testgen_test_lib",
        "@com_google_absl//absl/strings",
    ],
)
